/******************************************************************************************
**	SETUP - Examples:
*****************************************************************************************
*****************************************************************************************
* 1) Type
*		Date: $("#today").validity({valtype: "date"});
*		Email: $("#email").validity({valtype: "email"});
*		URL: $("#url").validity({valtype: "url"});
*		Number: $("#num").validity({valtype: "number"});
*		Alphanumeric: $("#alpanum").validity({valtype: "alphanum"});
*****************************************************************************************
* 2) Pattern
*		$("#phonenumber").validity({pattern:"^2[2-6]"}); (RegExp)
*****************************************************************************************
* 3) Value Length
*		$("#password).validity({ lengthmin: 4 });
*		$("#date).validity({ lengthmax: 8 });
*		$("#phonenumber").validity({ lengthequal: 10 });
*****************************************************************************************
* 4) Value Comparison
*  		$("#txtConfirmNewPassword").validity({ compare : { equal: "#txtNewPassword" } });
*		$("#txtNewPassword").validity({ compare : { notEqual: "#txtCurrentPassword" } });
*		$("#searchFrom").validity({compare : { equalSmaller: "#searchTo" } });
*		$("#searchTo").validity({compare : { equalBigger: "#searchFrom" } });
*****************************************************************************************
* 5) Required Elements
*		$("#txtNewPassword").validity({required:true});
*		$("[type='checkbox'][name='product']").validity({ required: { group:true } });
*****************************************************************************************
*****************************************************************************************
**	VALIDATION - Examples:
*****************************************************************************************
*****************************************************************************************
* 1) Submit Form
*	$("#myForm").bind("submit",function(){			
*		var $this = $(this);
*		var errs=$.checkValidity({
*			element: this,
*			template : error_template.inPopUp,
*			ajaxSubmit: {
*				target: $("#myForm"),
*				beforeSubmit:function(){
*					$("body").append("<div id='loading'>Loading</div>");
*				},
*				complete: function(){
*					$("#loading").remove();
*				},
*				error: function(){
*					alert("error")
*				},
*			callback: function(errors){
*					if(errors){	alert(errors);}
*				}
*		});
*		return errs;
*	});
*****************************************************************************************
* 2) Submit Form (2)
*	$("#myForm").bind("submit",function(){			
*		var $this = $(this);
*		var errs=$.checkValidity({
*			element: this,
*			template : error_template.inPopUp,
*			thickbox : {caption: "Submit my form", url: "some_url.html", iframe:true} ,
*			callback: function(errors){
*					if(errors){	alert(errors);}
*				}
*		});
*		return errs;
*	});
*****************************************************************************************
* 3) on Blur
*	$("#email").blur(function(){
*		$.checkValidity({
*			element: this,
*			template : error_template.inConsole,
*			callback: function(errors){(errors) ? console.debug(errors) : console.debug("Email is valid")}
*		});
*	});
*****************************************************************************************
*****************************************************************************************/

var attributes = [ "pattern", "required", "required-group-id", "compare-equal", "compare-equalbigger", "compare-equalsmaller", "compare-bigger", "compare-smaller", "compare-notequal", "valtype", "lengthmin", "lengthmax", "lengthequal" ];
var numcheck = /\d/;
var alphanumcheck = /[a-zA-Z]|[α-ωΑ-Ω]|[0-9]/;
var alphacheck = /^(([a-zA-Z]|[α-ωΑ-Ω]|\s)*)$/;
var datecheck = /(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.](19|20)\d\d/;
var emailcheck = /^\w+(\.\w+)*@[A-Za-z0-9]+(\.?\-?\w+)*(\.[A-Za-z]{2,4})$/;
var urlcheck = /^((https?:\/\/)|(w{3}\.))(([A-Za-z0-9])+(\.?\-?\w+)(\.[A-Za-z]{2,})+)((\/(\w+\.?)*)*)?((\?.+)*)?/ ;
var error_messages = { 
	defLang : "EN",
	EN : {
		heading 				: "<h1>Attention</h1><h2>The following errors occured:</h2>",
		required 				: "Is a required field",
		requiredGroup			: "At least one of the following is required",
		
		alpha					: "Must only consist of letters",
		alphanum				: "Must consist of letters and/or numbers",
		numeric 				: "Must consist of numbers",
		date 					: "Must be a date (e.g. 31\/12\/2005)",
		email 					: "Must be a valid E-mail address (e.g. smith.adam@gmail.com)",
		url 					: "Must be a valid URL (e.g. www.octavodia.com)",

		pattern					: "Must match the pattern [[VAR]]",

		compareEqual			: "Must be equal to '[[VAR]]'",
		compareEqualOrBigger	: "Must be equal to, or greater than, '[[VAR]]'",
		compareEqualOrSmaller	: "Must be equal to, or smaller than, '[[VAR]]'",
		compareBigger			: "Must be greater than '[[VAR]]'",
		compareSmaller			: "Must be less than '[[VAR]]'",
		compareNotEqual 		: "Must be different than '[[VAR]]'",
		
		lengthequal				: "Must consist of [[VAR]] characters",
		lengthmin				: "Must consist of [[VAR]] characters or more",
		lengthmax				: "Must consist of [[VAR]] characters or less",
		lengthrange				: "Must consist of between [[VAR]] and [[VAR_1]] characters"
		
	}
}; 
var error_template = {
	inPopUp : {
		error_heading	: "<h1>#text</h1>",
		error_title		: "<h3>#text</h3>",
		error_msg_container : "<ol>#text</ol>",
		error_msg_item : "<li>#text</li>"
	},
	inConsole:	{
		error_heading	: "#text",
		error_title		: "#text: \n",
		error_msg_container : "#text",
		error_msg_item : "- #text \n"
	},
	inDocument: {
		error_heading	: "",
		error_title		: "<h5>#text</h5>",
		error_msg_container : "<ol>#text</ol>",
		error_msg_item : "<li>#text</li>"
	}
};
(function($){$.extend($, {
	checkValidity : function(opts) {
		if (typeof opts != "object") {alert("Insufficient amount of options (element, attribute, template, callback)");return false;}
		getTitle = function(el){$e=$(el);return ($e.attr("title")) ? $e.attr("title") : $("label[for='"+$e.attr("id")+"']").eq(0).text();};
	//Highlight/Unhilight Elements with Errors (y = true/false)
		highlight = function(el,y){
			if(y){if($(el).attr("type")!="checkbox"){$(el).addClass("err");}$("label[for="+$(el).attr("id")+"]").eq(0).addClass("err");
			}else{$(el).removeClass("err");$("label[for="+$(el).attr("id")+"]").eq(0).removeClass("err");}
		}; //end highlight() Function
	
	//Init
		var $el = $(opts.element);
		var attr = (opts.attribute) ? opts.attribute : false;
		var template = (opts.template) ? opts.template : error_template.inConsole;
		var ajaxSubmit = (opts.ajaxSubmit) ? opts.ajaxSubmit : false;
		var thickBox = (opts.thickBox) ? opts.thickBox : false;
		var errors = "" ;

		var getAttribute = {
			input_value : function(element) { return $(element).val(); },
			input_title : function(element) { return getTitle($(element)); },
			input_checked : function(element) { return $(element).attr("checked"); },
			input_selected : function(element) { return $(element).attr("selected"); },
			input_type : function(element) { return $(element).attr("type"); },
			input_node : function(element) { return $(element).get(0).nodeName; }
		};
	
		if(getAttribute.input_node($el) == "FORM") {
			var $thisForm = $el;
			$el.find("input,select,textarea").each(function(){
				$el = {element : $(this),errors : ""};
				jQuery.each(attributes,function(){if ($el.element.attr(this)) {
					var attr = this;var attr_value = $el.element.attr(attr);
					var err = doCheck($el.element,attr,attr_value);
					if(err){$el.error_title =  err.split("||")[1];$el.errors += err.split("||")[0];}
				}});
				if($el.errors!=""){
					highlight($el.element,true);
					errors_b = template.error_title.replace(/#text/,$el.error_title)+template.error_msg_container.replace(/#text/,$el.errors);
					errors = (errors.indexOf(errors_b) == -1) ? errors+errors_b : errors;
				} else {highlight($el.element,false);}
			});
		} else {
			$el = {element : $el,errors : ""};
			jQuery.each(attributes,function(){if ($el.element.attr(this)) {
				var attr = this;var attr_value = $el.element.attr(attr);
				var err = doCheck($el.element,attr,attr_value);
				if(err){$el.error_title =  err.split("||")[1];$el.errors += err.split("||")[0];}
			}});
			if($el.errors!=""){
				highlight($el.element,true);
				errors_b = template.error_title.replace(/#text/,$el.error_title)+template.error_msg_container.replace(/#text/,$el.errors);
				errors = (errors.indexOf(errors_b) == -1) ? errors+errors_b : errors;
			} else {highlight($el.element,false);}
		}
	//Function to check validity of attributes
		function doCheck(element,attr,attr_value) {
			var $el = element; 
			var input_value = getAttribute.input_value($el);
			var input_title = getAttribute.input_title($el);
			var input_checked = getAttribute.input_checked($el);
			var input_selected = getAttribute.input_selected($el);
			var input_type = getAttribute.input_type($el);
			var pattern = new RegExp(attr_value);
			var errors_i = "";
			
			if (attr_value == "url"){
				if(window.console) {
					debug = input_value.replace(urlcheck,"domain: $4 \nfolder/file: $8 \nfile: $9 \nstring: $11\n ");
					//console.debug(urlcheck.test(input_value));
				}
			}
		//Check Type
			if (attr=="valtype" && input_value){
				if (attr_value == "number" && isNaN(input_value)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.numeric) ;}
				else if (attr_value == "alpha" && !alphacheck.test(input_value)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.alpha);}
				else if (attr_value == "alphanum" && !alphanumcheck.test(input_value)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.alphanum);}
				else if (attr_value == "date" && !datecheck.test(input_value)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.date);}
				else if (attr_value == "email" && !emailcheck.test(input_value)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.email);}
				else if (attr_value == "url" && !urlcheck.test(input_value)){ errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.url);}
			}
		//Check Pattern
			
			else if (attr=="pattern" && input_value && !pattern.test(input_value)){
				errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.pattern.replace(/\[\[VAR\]\]/,attr_value));
			}
		//Check Length
			else if (attr=="lengthequal" && input_value  && input_value.length != attr_value){
				errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.lengthequal.replace(/\[\[VAR\]\]/,attr_value));
			}
			else if (attr=="lengthmin" && input_value  && input_value.length < attr_value){
				errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.lengthmin.replace(/\[\[VAR\]\]/,attr_value));
			}
			else if (attr=="lengthmax" && input_value && input_value.length > attr_value){
				errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.lengthmax.replace(/\[\[VAR\]\]/,attr_value));
			}
		//Check Required
			else if (attr=="required"){
				if ((input_type=="text" && !input_value || input_type=="password" && !input_value) || (input_type=="radio" || input_type=="checkbox" && !input_checked) || (input_type=="select" && !input_selected)){errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.required);}
			}
			
		//Check Required Group
			else if (attr=="required-group-id") {
				var rgerr = false;
				if (input_type=="text" || input_type=="password") {
					if ( $("[required-group-id="+attr_value+"][value='']").length == $("[required-group-id="+attr_value+"]").length ){
						rgerr = true;
					}
				} else if (input_type=="radio" || input_type=="checkbox") {
					if ($("[required-group-id='"+attr_value+"'][checked='']").length == $("[required-group-id='"+attr_value+"']").length){
						rgerr = true;
					}
				}
				
				$("[required-group-id='"+attr_value+"']").each(function(){
					$this = $(this);
					highlight($this,false);
					if(rgerr) {	highlight($this,true); errors_i += template.error_msg_item.replace(/#text/,getTitle($this));} 
				});
				if(rgerr) {input_title = error_messages.EN.requiredGroup;}
				
			}
		//Check Comparison
			else if (attr=="compare-equal" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value!=attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqual.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				} else if(!numcheck.test(attr_value) && input_value!=$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqual.replace(/\[\[VAR\]\]/,getTitle($(attr_value))));
				}
			}
			else if (attr=="compare-equalbigger" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value<=attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualOrBigger.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				} else if(!numcheck.test(attr_value) && input_value<=$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualOrBigger.replace(/\[\[VAR\]\]/,getTitle($(attr_value))));
				}
			}
			else if (attr=="compare-equalsmaller" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value>=attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualOrSmaller.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				} else if(!numcheck.test(attr_value) && input_value>=$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualOrSmaller.replace(/\[\[VAR\]\]/,getTitle($(attr_value))));
				}
			}
			else if (attr=="compare-bigger" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value<attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualBigger.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				} else if(!numcheck.test(attr_value) && input_value<$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualBigger.replace(/\[\[VAR\]\]/,getTitle($(attr_value)))); 
				}
			}
			else if (attr=="compare-smaller" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value>attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualSmaller.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				} else if(!numcheck.test(attr_value) && input_value>$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareEqualSmaller.replace(/\[\[VAR\]\]/,getTitle($(attr_value)))); 
				}
			}
			else if (attr=="compare-notequal" && input_value){
			// Comparing Numbers
				if(numcheck.test(attr_value) && input_value==attr_value){
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareNotEqual.replace(/\[\[VAR\]\]/,attr_value));
			// Comparing Elements
				}else if(!numcheck.test(attr_value) && input_value==$(attr_value).val()) {
					errors_i += template.error_msg_item.replace(/#text/,error_messages.EN.compareNotEqual.replace(/\[\[VAR\]\]/,getTitle($(attr_value)))); 
				}
			}
			
			if(errors_i) {return errors_i+"||"+input_title; } else { return false;}
		}// end doCheck() Function
		
	// Callback Function
		if(opts.callback) {opts.callback(errors);}
	
	//ThickBox
		if(!errors && thickBox) {
			if($thisForm) { var queryString = $($thisForm).formSerialize();  }
			if(thickBox.iframe) {thickBox.iframe = "&TB_iframe="+thickBox.iframe;}
			if(thickBox.height) {thickBox.height = "&height="+thickBox.height;}
			if(thickBox.width) {thickBox.width = "&width="+thickBox.width;}
			tb_show(thickBox.caption, thickBox.url+"?"+queryString+thickBox.iframe+thickBox.height+thickBox.width,false);
		}
		
	//Ajax Submit
		if(!errors && $thisForm && ajaxSubmit) {$thisForm.ajaxSubmit(ajaxSubmit);}
		
	// Avoid form submition	
		if(errors || thickBox || ajaxSubmit) {errors=false;}
		
	//Return
		return errors;
	} // end checkValidity
});})(jQuery);


(function($){ // Set up of Attributes and Values Here
	jQuery.fn.validity = function(opts){
		var groupId = Math.random().toString();groupId = groupId.substring(2);
		return this.each(function(){		
		//Set Attributes and Values
			(opts) ?
				jQuery.each(opts, function(attr,value){
				// If Required Group
					(typeof value == "object") ?
						jQuery.each(value, function(a,v){(a.indexOf("group")!=-1) ? $this.attr(attr+"-"+a+"-id",groupId) : $this.attr(attr+"-"+a,v);})
						: $this.attr(attr,value); 
				})
			: alert("Error: Insufficient amount of options");
		}); // end return each
	};//end validity
})(jQuery);